﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.WebControls.WebParts;
using System.Windows.Forms;
using DataCapture.Helper;
using Google.Protobuf.WellKnownTypes;
using HslCommunication;
using Org.BouncyCastle.Ocsp;
using static DataCapture.Helper.PublicHelp;

namespace DataCapture.DeviceDataSave;

public class DeviceBase : DeviceDataCaptureBase
{
    private readonly int _cylinderStaartAddress = 0;//气缸起始地址
    private readonly PLCDataBase _plcDatabase;
    protected  DeviceData<List<AlarmData>> DeviceAlarmDataData;//MQ报警数据

    private readonly string[] _axleAddress;//轴地址列表
    private readonly ushort[] _axleLeg;//每个数据长度
    private readonly string[] _IOAddress;//IO地址列表
    //private readonly string[] _cylinderAddress;//气缸地址列表
    private readonly string[] _triggerAddress;//触发地址列表

    private readonly string[] _alarmAddress;//D告警地址列表
    private readonly string[] _alarmAddress_XY;//X、Y告警地址列表

    //private readonly string[] _IOAddress_XY;//IO信号地址列表

    public DeviceBase(string plcName, PublicHelp.ElementConfig elementConfig) : base(elementConfig)
    {
        this.plcName = plcName;//plc名称
        _plcDatabase = PLCProcessingHelper.Instance.GetPLCDataBase(plcName);//创建PLC连接
        DeviceAlarmDataData = new DeviceData<List<AlarmData>>();
        //初始化告警数据
        List<AlarmAddressConfig> alarmAddressConfigs = AddressConfigReader.AlarmReadConfigs(elementConfig.AlarmConfigFilePath);
        if (alarmAddressConfigs != null && alarmAddressConfigs.Count > 0)
        {

            for (int i = 0; i < alarmAddressConfigs.Count; i++)
            {
                AlarmAddressConfig alarmConfig = alarmAddressConfigs[i];

                // 避免重复判断 ContainsKey，直接使用 TryAdd 的返回值判断是否成功添加
                bool added = AlarmDatas.TryAdd(alarmConfig.alarmId, new AlarmData
                {
                    deviceID = elementConfig.DeviceId,
                    faultID = alarmConfig.alarmId,
                    alarmContan = alarmConfig.alarmContan,
                    createdTime = DateTime.Now
                });

                if (!added)
                {
                    Log4NetHelper.Debug($"告警地址有重复地址：{alarmConfig.alarmId}，请检查配置表：{elementConfig.AlarmConfigFilePath}", true);
                    continue;
                }
                AlarmConfig.TryAdd(alarmConfig.alarmId, alarmConfig);//添加配置
            }
            string addresStr = "";
            string addresStr_XY = "";
            string[] address = AlarmDatas.Keys.ToArray();

            List<string> listStr = [];
            List<string> listStrXy = [];
            for (int i = 0; i < address.Length; i++)
            {
                if (address[i].Substring(0, 1) == "D")
                {
                    string currentAddress = address[i].Split('.')[0];//D1100.1=>D1100
                    if (addresStr == currentAddress)
                    {//如果当前地址与上一次地址相同，则跳过
                        continue;
                    }

                    addresStr = currentAddress;
                    listStr.Add(currentAddress);
                }
                else
                {
                    string currentAddress = address[i];
                    if (addresStr_XY == currentAddress)
                    {//如果当前地址与上一次地址相同，则跳过
                        continue;
                    }

                    addresStr_XY = currentAddress;
                    listStrXy.Add(currentAddress);
                }

            }

            _alarmAddress = listStr.ToArray();
            _alarmAddress_XY = listStrXy.ToArray();
        }

        //初始化动作数据
        foreach (ModuleConfig moduleConfig in elementConfig.ModuleConfig)
        {
            switch (moduleConfig.ModuleType)
            {
                case "Cylinder"://气缸
                    _cylinderStaartAddress = moduleConfig.StartAddressValue();
                    //_cylinderAddress = moduleConfig.GetAddressList();

                    break;
                case "Axle"://轴 暂时没有一次性获取数据的功能

                    _axleAddress = moduleConfig.GetAddressList();

                    if (_axleAddress == null || _axleAddress.Length < 1)
                    {
                        break;
                    }
                    _axleLeg = new ushort[_axleAddress.Length];//初始化，需要两个16位长度，即是长度32位
                    for (int i = 0; i < _axleAddress.Length; i++)
                    {
                        _axleLeg[i] = 2;
                    }
                    break;
                case "IOCOM"://IOCOM
                    _IOAddress = moduleConfig.GetAddressList();
                    break;
                case "Trigger"://Trigger触发器（感应器、阻挡）
                    _triggerAddress = moduleConfig.GetAddressList();
                    break;
            }
        }
    }
    public override async void ReadActionData(CancellationToken cancellationToken, Action callAction)
    {
        if (_plcDatabase == null)
        {
            Log4NetHelper.Debug($"【{this.plcName}】对象尚未创建，请检PLC查初始话情况", true);
            return;
        }

        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                if (!_plcDatabase._isConnected || elementConfig.ModuleConfig == null)
                {
                    await Task.Delay(100, cancellationToken); // 控制循环频率
                    continue;
                }

                foreach (ModuleConfig moduleConfig in elementConfig.ModuleConfig)
                {//设备模块类型
                    switch (moduleConfig.ModuleType)
                    {
                        case "Cylinder":
                            if (string.IsNullOrEmpty(moduleConfig.StartAddress))
                            {
                                break;
                            }
                            try
                            {
                               
                                OperateResult<short[]> values = _plcDatabase.ReadInt16Data(moduleConfig.StartAddress, (ushort)moduleConfig.GetSize());
                                //OperateResult<ushort[]> values = _plcDatabase.TestReadUInt16Data(moduleConfig.StartAddress, (ushort)moduleConfig.GetSize());//测试数据
                                if (values != null && values.IsSuccess)
                                {
                                    DataParserCylinder(values.Content, moduleConfig);
                                }
                                //else
                                //{
                                //    Log4NetHelper.Debug($"读取Cylinder动作数据异常", true);

                                //}
                            }
                            catch (Exception ex)
                            {
                                Log4NetHelper.Debug($"读取Cylinder动作数据异常：{ex.Message}", true);

                                throw;
                            }

                            break;

                        case "Axle":
                            if (_axleAddress == null)
                            {
                                break;
                            }
                            try
                            {

                                OperateResult<byte[]> axleValues = _plcDatabase.RandomReadByName(_axleAddress, _axleLeg);
                                //OperateResult<int[]> axleValues = _plcDatabase.TestReadInt32Data(moduleConfig.StartAddress, 1);//测试数据
                                if (axleValues != null && axleValues.IsSuccess)
                                {
                                    DataParserAxle(axleValues.Content);
                                }
                                //else
                                //{
                                //    Log4NetHelper.Debug($"读取Axle动作数据异常", true);
                                //}
                            }
                            catch (Exception ex)
                            {
                                Log4NetHelper.Debug($"读取Axle动作数据异常：{ex.Message}", true);

                                throw;
                            }

                            break;

                        case "IOCOM":
                            if (_IOAddress == null)
                            {
                                break;
                            }
                            try
                            {

                                int[] iOValues = _plcDatabase.BatchReadXY(_IOAddress);
                                //OperateResult<int[]> axleValues = _plcDatabase.TestReadInt32Data(moduleConfig.StartAddress, 1);//测试数据
                                if (iOValues != null && iOValues.Length > 0)
                                {
                                    DataParserIOCOM(iOValues);
                                }
                                else
                                {
                                    Log4NetHelper.Debug($"读取IO数数据异常:数据为空", true);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log4NetHelper.Debug($"读取IO数据异常：{ex.Message}", true);

                                throw;
                            }

                            break;
                    }
                }
                callAction?.Invoke();//回调处理数据
                await Task.Delay(100, cancellationToken); // 控制循环频率 todo测试时候先用1000
            }
            catch (Exception ex)
            {
                Log4NetHelper.Debug($"读取【{deviceId}】动作数据异常：{ex.Message}", true);
            }
        }
    }
    public override async void ReadAlarmData(CancellationToken cancellationToken, Action callAction)
    {
        if (_plcDatabase == null)
        {
            Log4NetHelper.Debug($"【{this.plcName}】对象尚未创建，请检PLC查初始话情况", true);
            return;
        }
        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                if (!_plcDatabase._isConnected || _alarmAddress == null || _alarmAddress.Length == 0)
                {
                    await Task.Delay(100, cancellationToken); // 控制循环频率
                    continue;
                }
                //处理D开头数据
                AlarmMqDatas = new List<AlarmData>();
                if (_alarmAddress.Length > 0)
                {
                    OperateResult<byte[]> alarmValues = _plcDatabase.RandomReadByName(_alarmAddress);
                    //OperateResult<byte[]> alarmValues = _plcDatabase.TestUInt16RandomReadByName(_alarmAddress);
                    if (alarmValues != null && alarmValues.IsSuccess)
                    {
                        if (alarmValues.Content.Length == 0)
                        {
                            throw new ArgumentException("alarmValues 数组不能为空", nameof(alarmValues.Content));
                        }


                        SetAlarmData(alarmValues.Content);
                    }
                }
                //处理X、Y地开头的数据
                if (_alarmAddress_XY.Length > 0)
                {
                    List<int> vasList = new List<int>();

                    for (int i = 0; i < _alarmAddress_XY.Length; i++)
                    {
                        string address = _alarmAddress_XY[i];
                        OperateResult<bool[]> alarmValues = _plcDatabase.ReadBoolData(address, 1);//todo 要注意获取的数据是否能16位获取，因为地址是布尔值来的

                        if (alarmValues != null && alarmValues.IsSuccess)
                        {
                            if (alarmValues.Content.Length == 0)
                            {
                                throw new ArgumentException("alarmValues 数组不能为空", nameof(alarmValues.Content));

                            }

                            vasList.Add(alarmValues.Content[0] ? 1 : 0);
                        }
                        else
                        {
                            vasList.Add(-1);

                        }
                    }
                    SetAlarmData(vasList.ToArray());

                }

                callAction?.Invoke();
                await Task.Delay(100, cancellationToken); // 控制循环频率 todo测试时候先用1000

            }
            catch (Exception ex)
            {
                Log4NetHelper.Debug($"读取【{deviceId}】告警数据异常：{ex.Message}", true);

                throw;
            }
        }
    }

    public override async void ReadTriggerData(CancellationToken cancellationToken, Action callAction)
    {
        if (_plcDatabase == null)
        {
            Log4NetHelper.Debug($"【{this.plcName}】对象尚未创建，请检PLC查初始话情况", true);
            return;
        }

        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                if (!_plcDatabase._isConnected || elementConfig.ModuleConfig == null)
                {
                    await Task.Delay(100, cancellationToken); // 控制循环频率
                    continue;
                }

                foreach (ModuleConfig moduleConfig in elementConfig.ModuleConfig)
                {//设备模块类型
                    switch (moduleConfig.ModuleType)
                    {
                        case "Trigger":
                            if (_triggerAddress == null)
                            {
                                break;
                            }
                            try
                            {

                                int[] triggerVal = _plcDatabase.BatchReadXY(_triggerAddress);
                                if (triggerVal != null && triggerVal.Length > 0)
                                {
                                    DataParserTrigger(triggerVal);
                                }
                                else
                                {
                                    Log4NetHelper.Debug($"读取触发器数据异常:数据为空", true);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log4NetHelper.Debug($"读取触发器据异常：{ex.Message}", true);

                                throw;
                            } 
                            break;
                    }
                }
                callAction?.Invoke();//回调处理数据
                await Task.Delay(100, cancellationToken); // 控制循环频率 todo测试时候先用1000
            }
            catch (Exception ex)
            {
                Log4NetHelper.Debug($"读取【{deviceId}】动作数据异常：{ex.Message}", true);
            }
        }
    }

    //气缸数据处理
    public override void DataParserCylinder<T>(T ReadData, PublicHelp.ModuleConfig moduleConfig)
    {

        if (moduleConfig == null)
            throw new ArgumentNullException(nameof(moduleConfig));

        if (moduleConfig.PartList == null)
            return;

        var dataArray = ReadData as ushort[];
        if (dataArray == null)
            throw new ArgumentException("ReadData must be of type short[]", nameof(ReadData));

        try
        {
            foreach (PlcPart part in moduleConfig.PartList)
            {
                int offset = part.PartAddressValue() - _cylinderStaartAddress;

                if (offset < 0 || offset >= dataArray.Length)
                    continue; // 跳过非法偏移地址，防止越界

                bool closeOrOpen = dataArray[offset].GetBoolByIndex(2);
                //Log4NetHelper.Debug($"{part.PartName}:{part.PartType}:{part.PartAddress}:{closeOrOpen}", true);
                AddData(part.PartAddress, closeOrOpen ? 1 : 0);
            }
        }
        catch (IndexOutOfRangeException ex)
        {
            Log4NetHelper.Debug($"数据解析越界错误: {ex.Message}", true);
            throw;

        }
        catch (Exception ex) when (ex is InvalidCastException || ex is ArgumentException)
        {
            Log4NetHelper.Debug($"类型错误: {ex.Message}", true);
            throw;
        }
    }

    //public override void DataParserAxle<T>(T ReadData)
    //{
    //    try
    //    {
    //        if (ReadData is not int[] dataArray)
    //        {
    //            throw new ArgumentException("ReadData 必须是 int[] 类型", nameof(ReadData));
    //        }

    //        if (dataArray.Length == 0)
    //        {
    //            throw new ArgumentException("ReadData 数组不能为空", nameof(ReadData));
    //        }

    //        foreach (string PartAddress in _axleAddress)
    //        {
    //            int axleVal = dataArray[0]; // 只取本身的轴数据
    //            AddData(PartAddress, axleVal);
    //        }
    //    }
    //    catch (Exception e)
    //    { 
    //        Log4NetHelper.Debug($"DataParserAxle处理数据异常：{e.Message}", true);
    //        // 保留原始异常堆栈信息
    //        throw;
    //    }
    //}
    //轴数据处理
    public override void DataParserAxle<T>(T ReadData)
    {
        if (_axleAddress == null)
        {
            return;
        }
        try
        {
            if (ReadData is not byte[] dataArray)
            {
                throw new ArgumentException("ReadData 必须是 int[] 类型", nameof(ReadData));
            }

            if (dataArray.Length == 0)
            {
                throw new ArgumentException("ReadData 数组不能为空", nameof(ReadData));
            }
            //int offset = 0;


            for (int i = 0; i < _axleAddress.Length; i++)
            {
                int axleVal = BitConverter.ToInt32(dataArray, i * 4); // 默认小端序,每个 DWORD 占 4 字节
                //Log4NetHelper.Debug($"{_axleAddress[i]}:{axleVal}", true);
                AddData(_axleAddress[i], axleVal);
                //Console.WriteLine($"{_axleAddress[i]}: {axleVal}");
                //offset += 4; // 每个 DWORD 占 4 字节
            }
        }
        catch (Exception e)
        {
            Log4NetHelper.Debug($"DataParserAxle处理数据异常：{e.Message}", true);
            // 保留原始异常堆栈信息
            throw;
        }
    }
    //IO数据处理
    public override void DataParserIOCOM<T>(T ReadData)
    {
        if (_IOAddress == null)
        {
            return;
        }
        try
        {
            if (ReadData is not int[] dataArray)
            {
                throw new ArgumentException("ReadData 必须是 int[] 类型", nameof(ReadData));
            }

            if (dataArray.Length == 0)
            {
                throw new ArgumentException("ReadData 数组不能为空", nameof(ReadData));
            }
            //int offset = 0;
           

            for (int i = 0; i < _IOAddress.Length; i++)
            {
                int iOVal = dataArray[i];
                //Log4NetHelper.Debug($"{_IOAddress[i]}:{axleVal}", true);
                if (iOVal == -1)
                {
                    continue;
                }
                AddData(_IOAddress[i], iOVal);
            }
        }
        catch (Exception e)
        {
            Log4NetHelper.Debug($"v处理数据异常：{e.Message}", true);
            // 保留原始异常堆栈信息
            throw;
        }
    }

    public override void DataParserTrigger<T>(T ReadData)
    {
        if (_triggerAddress == null)
        {
            return;
        }
        try
        {
            if (ReadData is not int[] dataArray)
            {
                throw new ArgumentException("ReadData 必须是 int[] 类型", nameof(ReadData));
            }

            if (dataArray.Length == 0)
            {
                throw new ArgumentException("ReadData 数组不能为空", nameof(ReadData));
            }
            //int offset = 0;


            for (int i = 0; i < _triggerAddress.Length; i++)
            {
                int iOVal = dataArray[i];
                //Log4NetHelper.Debug($"{_IOAddress[i]}:{axleVal}", true);
                if (iOVal == -1)
                {
                    continue;
                }
                AddData(_triggerAddress[i], iOVal);
            }
        }
        catch (Exception e)
        {
            Log4NetHelper.Debug($"触发器处理数据异常：{e.Message}", true);
            // 保留原始异常堆栈信息
            throw;
        }
    }

    /// <summary>
    /// 设置告警数据
    /// </summary>
    /// <param name="deviceID"></param>
    /// <param name="alarmAddressConfig"></param>
    private void SetAlarmData(byte[] alarmValues)
    {

        //int offset = 0;
        for (int i = 0; i < _alarmAddress.Length; i++)
        {
            ushort readUInt16 = BitConverter.ToUInt16(alarmValues, i * 2); // 默认小端序,占 2 字节
            bool[] decodeData = DeviceDataProcessingHelper.Decode(readUInt16);//解码
                                                                              //bool[] decodeData = DeviceDataProcessingHelper.TestDecode(readUInt16);//解码  todo 测试
            string address = _alarmAddress[i];
            for (int j = 0; j < decodeData.Length; j++)
            {
                char suffix = DeviceDataProcessingHelper.GetLetterLabel(j);//后缀（Aiss码）
                string alarmId = $"{address}.{suffix}";//如：D1017.a
                bool statusData = decodeData[j];

                //Log4NetHelper.Error($"{deviceId}配置表{alarmId}", true);

                if (!AlarmDatas.TryGetValue(alarmId, out var alarmData))
                {//过滤配置表没有的地址
                    continue;
                }

                alarmData.alarmLevel = 0;
                alarmData.alarmTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                alarmData.createdTime = DateTime.Now;
                int offOn = statusData ? 1 : 0;
                if (alarmData.status != offOn)
                {
                    //更新当前状态
                    alarmData.status = offOn;
                    UploadAlarmData(alarmData);
                    //mq告警
                    //Log4NetHelper.Info($"告警：{dic_alarmId}", true);
                    if (statusData)
                    {
                        AlarmMqDatas.Add(alarmData);
                    }
                    //AlarmMqDatas.Add(alarmData);//todo 测试发送mq
                }
                else
                {
                    alarmData.status = offOn;
                }


                AlarmDatas[alarmId] = alarmData;
            }
            //offset += 2; //占 2 字节
        }


    }
    /// <summary>
    /// 设置告警数据
    /// </summary>
    /// <param name="deviceID"></param>
    /// <param name="alarmAddressConfig"></param>
    private void SetAlarmData(int[] alarmValues)
    {
        if (alarmValues != null && alarmValues.Length > 0)
        {
            if (alarmValues.Length != _alarmAddress_XY.Length)
            {
                Log4NetHelper.Error($"XY数据长度不匹配", true);

                return;
            }
            for (int i = 0; i < _alarmAddress_XY.Length; i++)
            {
                if (alarmValues[i] == -1)
                {
                    continue;
                }
                int offOn = alarmValues[i];
                string alarmId = _alarmAddress_XY[i];

                //Log4NetHelper.Error($"{deviceId}配置表{alarmId}", true);

                if (!AlarmDatas.TryGetValue(alarmId, out var alarmData))
                {//过滤配置表没有的地址
                    continue;
                }

                if (AlarmConfig.TryGetValue(alarmId, out var addressConfigs))
                {
                    alarmData.alarmLevel = 0;
                    alarmData.alarmTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                    alarmData.createdTime = DateTime.Now;
                    if (alarmData.status != offOn)
                    {
                        //更新当前状态
                        alarmData.status = offOn;
                        UploadAlarmData(alarmData);
                        //mq告警
                        //Log4NetHelper.Info($"告警：{dic_alarmId}", true);
                        if ($"{offOn}" == addressConfigs.trigger)
                        {
                            AlarmMqDatas.Add(alarmData);
                        }
                    }
                    else
                    {
                        alarmData.status = offOn;
                    }


                    AlarmDatas[alarmId] = alarmData;
                    //offset += 2; //占 2 字节
                }
            }
        }
    }
    /// <summary>
    /// 上传告警数据
    /// </summary>
    /// <param name="alarm"></param>
    private void UploadAlarmData(AlarmData alarm)
    {
        if (DapperHelper.Instance.isConnect)
        {
            bool result = DataProcessor.InsertAlarmData(alarm);
            if (result)
            {
                //Log4NetHelper.Info($"插入设备{deviceID}告警数据：{alarmId},值:{alarmVal}", true);
            }
            else
            {
                Log4NetHelper.Error($"插入设备【{alarm.deviceID}】告警{alarm.faultID}数据失败", true);

            }
        }
    }
}